/*
 MXml - XML Library for Mobile Processing
 
 Copyright (c) 2005-2007 Francis Li
 Copyright (c) 2007-2008 Mary Jane Soft - Marlon J. Manrique
 	
 http://mobile.processing.org
 http://mjs.darkgreenmedia.com
 http://marlonj.darkgreenmedia.com	
 	
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 	
 You should have received a copy of the GNU Lesser General
 Public License along with this library; if not, write to the
 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 Boston, MA  02111-1307  USA
 	
 $Id: MXml.java 375 2008-02-28 14:39:27Z marlonj $
 
*/

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.kxml2.io.KXmlParser;

import processing.core.PMIDlet;

import processing.xml.XMLElement;
import processing.xml.XMLParser;

/**
 * MXMLParser
 *
 * This class is based on the oficial XMLParser class, only adds entities
 * support
 *
 * This class is a copy of the XMLParser cause the attributes are private and 
 * can't be accessed
 *
 * @see XMLParser
 */
public class MXMLParser extends XMLParser
{
  // Copy of the attributes of the XMLParser
  // they are private in the super class
  PMIDlet     midlet;
  KXmlParser  parser;
  Thread      thread;

  /**
   * Create XML Parser
   *
   * @see XMLParser(PMIDlet) 
   */
  public MXMLParser(PMIDlet midlet)
  {
    super(midlet);
    this.midlet = midlet;
    parser = new KXmlParser();
  }

  /**
   * Start parsing the document
   *
   * @see XMLParser(InputStream) 
   */
  public void start(InputStream is) {
    synchronized (this) {
      if (thread == null) {
        try {
          parser.setInput(new InputStreamReader(is));
          // CHANGE : Add entity replacement to xhtml blank space
          parser.defineEntityReplacementText("nbsp"," ");   
          parser.defineEntityReplacementText("copy"," ");   
          thread = new Thread(this);
          thread.start();
        } 
        catch (Exception e) {
          throw new RuntimeException(e.getMessage());
        }
      } 
      else {
        throw new RuntimeException("Parser is already running");
      }
    }
  }

  // Copy of the super class methods 

  public void stop() {
    synchronized (this) {
      thread = null;
    }
  }

  public String attribute(String name) {
    if (parser != null) {
      return parser.getAttributeValue(null, name);
    } 
    else {
      throw new RuntimeException("Parser not running");
    }
  }

  public void run() {
    Thread current = Thread.currentThread();
    while (thread == current) {
      try {
        int event = parser.next();
        String data = null;
        switch (event) {
        case EVENT_TAG_START:
        case EVENT_TAG_END:
          data = parser.getName();
          break;
        case EVENT_TEXT:
          data = parser.getText();
          break;
        }
        synchronized (this) {
          midlet.enqueueLibraryEvent(this, event, data);
          wait();
        }
        if (event == EVENT_DOCUMENT_END) {
          break;
        }
      } 
      catch (Exception e) {
        throw new RuntimeException(e.getMessage());
      }
      Thread.yield();
    }
    synchronized (this) {
      if (thread == current) {
        thread = null;                
      }
    }
  }
}
